package com.wenx.v3system.modular.cloud.controller;

import com.wenx.base.rest.BaseRestController;
import com.wenx.v3core.response.R;
import com.wenx.v3secure.annotation.RequiresPermissions;
import com.wenx.v3secure.enums.SystemPermission;
import com.wenx.v3system.modular.cloud.domain.dto.SysRoleDto;
import com.wenx.v3system.modular.cloud.domain.query.SysRoleQuery;
import com.wenx.v3system.modular.cloud.service.SysRoleRestService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.*;

import static com.wenx.v3secure.annotation.RequiresPermissions.Logical.OR;

/**
 * 角色管理Controller
 * 提供角色的CRUD操作和权限管理功能
 *
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Tag(name = "角色管理API")
@RestController
@RequestMapping("/api/v3/sys/roles")
public class SysRoleRestController extends BaseRestController<SysRoleDto, SysRoleQuery, SysRoleRestService> {

    public SysRoleRestController(SysRoleRestService service) {
        super(service);
    }

    @Override
    @PostMapping("/page")
    @Operation(summary = "分页查询角色", description = "根据查询条件分页获取角色列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R page(@RequestBody SysRoleQuery query) {
        return R.ok(service.page(query));
    }

    /**
     * 获取所有角色（不分页）
     */
    @GetMapping("/all")
    @Operation(summary = "获取所有角色", description = "获取所有角色列表，不分页")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R getAllRoles() {
        return R.ok(service.all());
    }

    @Override
    @GetMapping("/get/{id}")
    @Operation(summary = "获取角色详情", description = "根据角色ID获取角色详细信息")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R get(@PathVariable Serializable id) {
        return R.ok(service.get(id));
    }

    @Override
    @PostMapping("/add")
    @Operation(summary = "新增角色", description = "创建新的角色")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_ALL_CODE}, logical = OR)
    public R add(@RequestBody SysRoleDto dto) {
        service.add(dto);
        return R.ok();
    }

    @Override
    @PutMapping("/update")
    @Operation(summary = "更新角色", description = "更新角色信息")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_ALL_CODE}, logical = OR)
    public R update(@RequestBody SysRoleDto dto) {
        service.update(dto);
        return R.ok();
    }

    @Override
    @DeleteMapping("/delete/{id}")
    @Operation(summary = "删除角色", description = "根据角色ID删除角色")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_ALL_CODE}, logical = OR)
    public R delete(@PathVariable Serializable id) {
        service.delete(id);
        return R.ok();
    }

    /**
     * 获取用户的角色列表
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取用户角色", description = "获取指定用户的角色列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R getUserRoles(@PathVariable Long userId) {
        return R.ok(service.getUserRoles(userId));
    }

    /**
     * 获取角色的权限列表
     */
    @GetMapping("/{roleId}/permissions")
    @Operation(summary = "获取角色权限", description = "获取角色的权限列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R getRolePermissions(@PathVariable Long roleId) {
        return R.ok(service.getRolePermissions(roleId));
    }

    /**
     * 为角色分配权限（支持权限代码和权限ID）
     */
    @PutMapping("/{roleId}/permissions")
    @Operation(summary = "分配角色权限", description = "为角色分配权限（支持权限代码和权限ID）")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_MANAGE_CODE}, logical = OR)
    public R assignRolePermissions(@PathVariable Long roleId, @RequestBody Object permissionData) {
        log.info("角色权限分配请求，角色ID: {}, 权限数据类型: {}", roleId, permissionData.getClass().getSimpleName());
        
        service.assignPermissionsToRoleByData(roleId, permissionData);
        return R.ok();
    }

    /**
     * 检查角色编码是否存在
     */
    @GetMapping("/check-code")
    @Operation(summary = "检查角色编码", description = "检查角色编码是否已存在")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R checkRoleCode(@RequestParam String code, @RequestParam(required = false) Long excludeId) {
        boolean exists = service.existsByCode(code, excludeId);
        return R.ok(Map.of("exists", exists));
    }

    /**
     * 启用角色
     */
    @PutMapping("/{roleId}/enable")
    @Operation(summary = "启用角色", description = "启用指定角色")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_MANAGE_CODE}, logical = OR)
    public R enableRole(@PathVariable Long roleId) {
        service.enableRole(roleId);
        return R.ok();
    }

    /**
     * 停用角色
     */
    @PutMapping("/{roleId}/disable")
    @Operation(summary = "停用角色", description = "停用指定角色")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_MANAGE_CODE}, logical = OR)
    public R disableRole(@PathVariable Long roleId) {
        service.disableRole(roleId);
        return R.ok();
    }

    /**
     * 获取角色菜单权限
     */
    @GetMapping("/{roleId}/menus")
    @Operation(summary = "获取角色菜单权限", description = "获取角色的菜单权限列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_READ_CODE}, logical = OR)
    public R getRoleMenus(@PathVariable Long roleId) {
        List<Long> menuIds = service.getRoleMenus(roleId);
        return R.ok(menuIds);
    }

    /**
     * 分配角色菜单权限
     */
    @PostMapping("/{roleId}/menus")
    @Operation(summary = "分配角色菜单权限", description = "为角色分配菜单权限")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.ROLE_MANAGE_CODE}, logical = OR)
    public R assignMenusToRole(@PathVariable Long roleId, @RequestBody List<Long> menuIds) {
        service.assignMenusToRole(roleId, menuIds);
        return R.ok();
    }
}
